/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.inmp.task;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.jms.JMSException;

import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;

import com.sinodata.bsm.common.vo.CollectField;
import com.sinodata.bsm.common.vo.Property;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResPropertyValue;
import com.sinodata.bsm.common.vo.ResPropertyValue.PropValue;
import com.sinodata.bsm.inmp.cache.CacheFactory;
import com.sinodata.bsm.inmp.cache.CollectFieldCache;
import com.sinodata.bsm.inmp.cache.PropertyCache;
import com.sinodata.bsm.inmp.cache.ResCache;
import com.sinodata.bsm.inmp.conf.InmpPropBean;
import com.sinodata.bsm.inmp.message.Messenger;
import com.sinodata.bsm.inmp.opconf.OpDbServiceUtil;
import com.sinodata.bsm.inmp.opconf.OpSqlGenerator;
import com.sinodata.bsm.inmp.util.DBConnectionUtil;
import com.sinodata.bsm.inmp.util.FilePersistUtil;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangyazhou
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-6-7 下午5:03:47          wangyazhou        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
@SuppressWarnings("deprecation")
public class OpIfPropJob implements StatefulJob {

    private static final Logger logger = Logger.getLogger("opprop");

    private ResCache resCache = (ResCache) CacheFactory.getCache(ResCache.class);

    private PropertyCache propertyCache = (PropertyCache) CacheFactory.getCache(PropertyCache.class);

    private CollectFieldCache fieldCache = (CollectFieldCache) CacheFactory.getCache(CollectFieldCache.class);

    Pattern opifPat = Pattern.compile(".*_(\\d+)$");

    private static final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat statdata_sf = new SimpleDateFormat("M_d_yyyy");

    private static final String OP_IF_FILE = "op_if";
    private static final String OP_RMC_FILE = "op_rmc";

    /**
     * 0 获取op数据库当前的时间
     * 1 获取上次获取指标的时间
     * 2 获取当前用来存端口性能数据的表
     * 3 获取最近一段时间的端口历史性能数据
     * 4 把数据与资源相匹配 并放入指标对列
     * 5 response  cpu  mem 分别同3 4 步
     */
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {

        String lastTime = "";
        String now = "";
        String table = "";
        //数据库中的当前时间
        try {
            now = OpDbServiceUtil.getInstance().getSingleDbValue("select now()");
        } catch (Exception e) {
            logger.error("[ERROR]\tFailed when get postgre current time ", e);
            return;
        }

        try {
            lastTime = (String) FilePersistUtil.getPersistentData(OP_IF_FILE);
        } catch (Exception e) {
            lastTime = "";
        }

        if (lastTime == null || lastTime.length() < 1) {
            try {
                FilePersistUtil.savePersistentData(OP_IF_FILE, now);
            } catch (Exception e2) {
                logger.error(e2);
            }
            return;
        }

        try {
            table = OpDbServiceUtil.getInstance().getSingleDbValue(OpSqlGenerator.buildIfRawTableSql());
        } catch (Exception e) {
        }

        //端口性能
        String ifSql = OpSqlGenerator.buildIfRawPropSql(table, lastTime, now);
        List<InmpPropBean> ifPropList = fetchProps(ifSql);
        sendIfProp(ifPropList);
        try {
            FilePersistUtil.savePersistentData(OP_IF_FILE, now);
        } catch (Exception e) {
            e.printStackTrace();
        }

        /**
         * 内存 CPU 响应时间 指标
         */
        String sTime = "";
        String eTime = "";
        try {
            sTime = (String) FilePersistUtil.getPersistentData(OP_RMC_FILE);
        } catch (Exception e) {
            sTime = "";
        }

        if (sTime == null || sTime.length() < 1) {
            try {
                FilePersistUtil.savePersistentData(OP_RMC_FILE, sf.parse(now).getTime() + "");
            } catch (Exception e2) {
                logger.error(e2);
            }
            return;
        }

        try {
            eTime = sf.parse(now).getTime() + "";
        } catch (Exception e) {
            logger.error(e);
        }

        String stats_day = statdata_sf.format(Calendar.getInstance().getTime());
        //CPU性能
        String cpuSql = OpSqlGenerator.buildCpuUtilizationSql("statsdata" + stats_day, sTime, eTime);
        List<InmpPropBean> cpuList = fetchProps(cpuSql);
        sendRMCProps(cpuList, 311100000000002L);
        //mem
        String memSql = OpSqlGenerator.buildMemUtilizationSql("statsdata" + stats_day, sTime, eTime);
        List<InmpPropBean> memList = fetchProps(memSql);
        sendRMCProps(memList, 311100000000003L);
        //response
        String respSql = OpSqlGenerator.buildResponseSql("statsdata" + stats_day, sTime, eTime);
        List<InmpPropBean> respList = fetchProps(respSql);
        sendRMCProps(respList, 311100000000001L);

        try {
            FilePersistUtil.savePersistentData(OP_RMC_FILE, sf.parse(now).getTime() + "");
        } catch (Exception e2) {
            logger.error(e2);
        }

    }

    /**
     * 发送设备响应时间指标
     * @param respList
     */
    private void sendRMCProps(List<InmpPropBean> respList, Long propId) {
        if (respList == null) {
            return;
        }
        logger.info("[TIP]\tsize==" + respList.size());
        for (InmpPropBean bean : respList) {
            if (bean.getValues().length != 1) {
                continue;
            }
            ResPropertyValue value = new ResPropertyValue();
            Res res = resCache.getResIdByIId(bean.getKey());
            if (res == null) {
                continue;
            }
            value.setResId(res.getId());
            value.setTaskId(-2L);
            value.setTemporary(false);
            try {
                value.setTime(sf.parse(bean.getTime()));
            } catch (Exception e) {
                value.setTime(Calendar.getInstance().getTime());
            }

            List<PropValue> propValueList = new ArrayList<PropValue>();
            for (int i = 1; i <= 1; i++) {
                Property property = propertyCache.get(propId);
                if (property == null) {
                    continue;
                }
                CollectField field = fieldCache.getByPropId(propId);
                PropValue propValue = ResPropertyValue.createPropValue(propId, bean.getValues()[i - 1], field.getFieldName());
                propValueList.add(propValue);
            }
            value.setValues(propValueList.toArray(new PropValue[propValueList.size()]));
            sendPropertyValue(value);
        }
    }

    /**
     * 把端口指标数据发送到MQ队列
     * @param ifPropList
     */
    public void sendIfProp(List<InmpPropBean> ifPropList) {
        if (ifPropList == null) {
            logger.info("[INFO]\t端口查询结果数为0" + new Date());
            return;
        }
        logger.info("[TIP]\tsize==" + ifPropList.size());
        for (InmpPropBean bean : ifPropList) {
            if (bean.getValues().length != 8) {
                continue;
            }
            ResPropertyValue value = new ResPropertyValue();
            Res res = resCache.getResByIIdForOpIF(bean.getKey());
            if (res == null) {
                continue;
            }
            value.setResId(res.getId());
            value.setTaskId(-2L);
            value.setTemporary(false);
            try {
                value.setTime(sf.parse(bean.getTime()));
            } catch (Exception e) {
                value.setTime(Calendar.getInstance().getTime());
            }

            List<PropValue> propValueList = new ArrayList<PropValue>();
            for (int i = 1; i <= 8; i++) {
                Long propId = Long.parseLong("32110100000000" + i);
                Property property = propertyCache.get(propId);
                if (property == null) {
                    continue;
                }
                CollectField field = fieldCache.getByPropId(propId);
                PropValue propValue = ResPropertyValue.createPropValue(propId, bean.getValues()[i - 1], field.getFieldName());
                propValueList.add(propValue);
            }
            value.setValues(propValueList.toArray(new PropValue[propValueList.size()]));
            sendPropertyValue(value);
        }
    }

    /**
     * 
     * @param value
     * @param scale
     * @param roundingMode
     * @return
     */
    public static double round(double value, int scale, int roundingMode) {
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(scale, roundingMode);
        double d = bd.doubleValue();
        bd = null;
        return d;
    }

    /**
     * 发送实时指标值到center的队列中。
     */
    private void sendPropertyValue(ResPropertyValue valuex) {
        try {
            Messenger.getInstance().sendPropertyValue(valuex);
        } catch (JMSException e) {
            logger.error("failed to send property value:" + valuex, e);
        }
    }

    /**
     * 通过sql获取一段时间内的历史性能数据
     * @param sql
     * @return
     */
    private List<InmpPropBean> fetchProps(String sql) {

        logger.info(sql);

        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        ResultSetMetaData rsMetaData = null;
        List<InmpPropBean> values = new ArrayList<InmpPropBean>();
        try {
            conn = DBConnectionUtil.getInstance().getManagerConnection();
            statement = conn.createStatement();
            rs = statement.executeQuery(sql);
            if (rs == null) {
                return null;
            }
            rsMetaData = rs.getMetaData();
            int numberOfColumns = rsMetaData.getColumnCount();
            while (rs.next()) {
                InmpPropBean bean = new InmpPropBean();
                bean.setKey(rs.getString(1));
                bean.setTime(rs.getString(2));
                String[] value = new String[numberOfColumns - 2];
                for (int i = 3; i <= numberOfColumns; i++) {
                    value[i - 3] = rs.getString(i);
                }
                bean.setValues(value);
                values.add(bean);
            }
        } catch (Exception e) {
            return null;
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException ex) {

                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException ex) {

                }
            }
            DBConnectionUtil.getInstance().returnConn(conn);
        }
        return values;
    }

    public static void main(String[] args) throws Exception {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sf.parse(sf.format(1372314982099L));
        System.out.println(d.toLocaleString());
    }
}
